#include <arm_neon.h>

void Gemm8x8(float *input, float *weight, float *output) __attribute__((aligned(32)));

void Gemm8x8(float *input, float *weight, float *output)
{
    float32x4_t input4[8];
    float32x4_t weight4[8];
    volatile float32x4_t output4[16];

    for (int i = 0; i < 8; i++,  input += 4) {
        input4[i] = vld1q_f32(input);
    }

    for (int i = 0; i < 8; i++,  weight += 4) {
        weight4[i] = vld1q_f32(weight);
    }

    float32x4_t *ptr = output4;
    for (int i = 0; i < 8; i++, ptr += 2, output += 8) {
        ptr[0] = vdupq_n_f32(0);
        ptr[1] = vdupq_n_f32(0);
        ptr[0] = vmlaq_laneq_f32(ptr[0], weight4[0], input4[i], 0);
        ptr[1] = vmlaq_laneq_f32(ptr[1], weight4[1], input4[i], 0);
        ptr[0] = vmlaq_laneq_f32(ptr[0], weight4[2], input4[i], 1);
        ptr[1] = vmlaq_laneq_f32(ptr[1], weight4[3], input4[i], 1);
        ptr[0] = vmlaq_laneq_f32(ptr[0], weight4[4], input4[i], 2);
        ptr[1] = vmlaq_laneq_f32(ptr[1], weight4[5], input4[i], 2);
        ptr[0] = vmlaq_laneq_f32(ptr[0], weight4[6], input4[i], 3);
        ptr[1] = vmlaq_laneq_f32(ptr[1], weight4[7], input4[i], 3);
        vst1q_f32(output, ptr[0]);
        vst1q_f32(output + 4, ptr[1]);
    }
}

